package management;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 学生成绩管理系统核心类：CSV文本存储（可读），包含所有核心方法
 */
public class StudentScoreSystem {
    private List<Student> studentList = new ArrayList<>();
    private List<Course> courseList = new ArrayList<>();
    private List<Score> scoreList = new ArrayList<>();
    private static final String DATA_FILE = "system_data/student_score.csv";

    // 构造方法：检查并创建存储目录
    public StudentScoreSystem() {
        checkAndCreateDir();
    }

    /**
     * 检查存储目录是否存在，不存在则创建
     */
    private void checkAndCreateDir() {
        File dataFile = new File(DATA_FILE);
        File parentDir = dataFile.getParentFile();
        if (parentDir != null && !parentDir.exists()) {
            boolean isCreated = parentDir.mkdirs();
            if (isCreated) {
                System.out.println("存储目录不存在，已自动创建：" + parentDir.getAbsolutePath());
            } else {
                System.err.println("存储目录创建失败：" + parentDir.getAbsolutePath() + "（可能权限不足）");
            }
        }
    }

    // ---------------------- 核心方法1：添加课程（之前遗漏，现在补全） ----------------------
    public void addCourse(Course course) {
        if (findCourseById(course.getCourseId()) != null) {
            System.out.println("课程编号 " + course.getCourseId() + " 已存在，添加失败");
            return;
        }
        courseList.add(course);
        System.out.println("课程添加成功：" + course);
    }

    // ---------------------- 核心方法2：添加学生（之前遗漏，现在补全） ----------------------
    public void addStudent(Student student) {
        if (findStudentById(student.getStudentId()) != null) {
            System.out.println("学号 " + student.getStudentId() + " 已存在，添加失败");
            return;
        }
        studentList.add(student);
        System.out.println("学生添加成功：" + student);
    }

    // ---------------------- 核心方法3：添加成绩（之前遗漏，现在补全） ----------------------
    public void addScore(String studentId, String courseId, double score) {
        // 1. 校验学生和课程是否存在
        Student student = findStudentById(studentId);
        if (student == null) {
            System.out.println("学号 " + studentId + " 不存在，成绩添加失败");
            return;
        }
        Course course = findCourseById(courseId);
        if (course == null) {
            System.out.println("课程编号 " + courseId + " 不存在，成绩添加失败");
            return;
        }

        // 2. 校验是否重复添加
        for (Score s : student.getStudentScores()) {
            if (s.getCourse().getCourseId().equals(courseId)) {
                System.out.println("学生 " + studentId + " 在课程 " + courseId + " 的成绩已存在，无需重复添加");
                return;
            }
        }

        // 3. 添加成绩（处理无效成绩异常）
        try {
            Score newScore = new Score(student, course, score);
            scoreList.add(newScore);
            System.out.println("成绩添加成功：" + newScore);
        } catch (InvalidScoreException e) {
            System.err.println("成绩添加失败：" + e.getMessage());
        }
    }

    // ---------------------- 核心方法4：按课程编号查询成绩 ----------------------
    public List<Score> queryScoresByCourseId(String courseId) {
        List<Score> result = new ArrayList<>();
        Course course = findCourseById(courseId);
        if (course == null) {
            System.out.println("课程编号 " + courseId + " 不存在");
            return result;
        }
        result = course.getCourseScores();
        if (result.isEmpty()) {
            System.out.println("课程编号 " + courseId + " 暂无成绩记录");
        }
        return result;
    }

    // ---------------------- 核心方法5：按课程名称查询成绩 ----------------------
    public List<Score> queryScoresByCourseName(String courseName) {
        List<Score> result = new ArrayList<>();
        for (Course course : courseList) {
            if (course.getName().equals(courseName)) {
                result.addAll(course.getCourseScores());
            }
        }
        if (result.isEmpty()) {
            System.out.println("课程 " + courseName + " 暂无成绩记录");
        }
        return result;
    }

    // ---------------------- 核心方法6：计算学生GPA ----------------------
    public double calculateGPA(String studentId) {
        Student student = findStudentById(studentId);
        if (student == null) {
            System.out.println("学号 " + studentId + " 不存在");
            return 0.0;
        }

        double totalGradePoints = 0.0;
        int totalCredits = 0;

        for (Score score : student.getStudentScores()) {
            if (score.getScore() >= 60) { // 仅统计及格成绩
                double gradePoint = score.getScore() / 20; // 绩点规则：80分=4.0，90分=4.5
                totalGradePoints += gradePoint * score.getCourse().getCredit();
                totalCredits += score.getCourse().getCredit();
            }
        }

        if (totalCredits == 0) {
            System.out.println(student.getName() + " 无及格课程，GPA为0.0");
            return 0.0;
        }

        return Math.round((totalGradePoints / totalCredits) * 100.0) / 100.0;
    }

    // ---------------------- 核心方法7：CSV格式保存数据（文本可读） ----------------------
    public void saveData() {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(DATA_FILE))) {
            // 1. 写入课程数据（格式：课程编号,课程名称,学分）
            writer.write("===课程数据===");
            writer.newLine();
            for (Course course : courseList) {
                writer.write(course.getCourseId() + "," + course.getName() + "," + course.getCredit());
                writer.newLine();
            }

            // 2. 写入学生数据（格式：学号,姓名,班级）
            writer.write("===学生数据===");
            writer.newLine();
            for (Student student : studentList) {
                writer.write(student.getStudentId() + "," + student.getName() + "," + student.getClassName());
                writer.newLine();
            }

            // 3. 写入成绩数据（格式：学号,课程编号,成绩）
            writer.write("===成绩数据===");
            writer.newLine();
            for (Score score : scoreList) {
                String studentId = score.getStudent().getStudentId();
                String courseId = score.getCourse().getCourseId();
                writer.write(studentId + "," + courseId + "," + score.getScore());
                writer.newLine();
            }

            System.out.println("数据保存成功！CSV文件路径：" + new File(DATA_FILE).getAbsolutePath());
        } catch (IOException e) {
            System.err.println("数据保存失败：" + e.getMessage());
        }
    }

    // ---------------------- 核心方法8：从CSV格式加载数据 ----------------------
    public void loadData() {
        File dataFile = new File(DATA_FILE);
        if (!dataFile.exists()) {
            System.out.println("无历史数据，将创建新系统");
            return;
        }

        // 临时集合：存储加载的课程/学生/成绩
        List<Course> loadedCourses = new ArrayList<>();
        List<Student> loadedStudents = new ArrayList<>();
        List<Score> loadedScores = new ArrayList<>();

        try (BufferedReader reader = new BufferedReader(new FileReader(DATA_FILE))) {
            String line;
            String dataType = ""; // 标记当前读取的是“课程/学生/成绩”数据

            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (line.isEmpty()) continue;

                // 识别数据类型标记
                if (line.equals("===课程数据===")) {
                    dataType = "course";
                    continue;
                } else if (line.equals("===学生数据===")) {
                    dataType = "student";
                    continue;
                } else if (line.equals("===成绩数据===")) {
                    dataType = "score";
                    continue;
                }

                // 按数据类型解析内容
                switch (dataType) {
                    case "course":
                        // 解析课程：课程编号,课程名称,学分
                        String[] courseParts = line.split(",");
                        if (courseParts.length == 3) {
                            String courseId = courseParts[0];
                            String name = courseParts[1];
                            int credit = Integer.parseInt(courseParts[2]);
                            Course course = new Course(courseId, name, credit);
                            loadedCourses.add(course);
                        }
                        break;

                    case "student":
                        // 解析学生：学号,姓名,班级
                        String[] studentParts = line.split(",");
                        if (studentParts.length == 3) {
                            String studentId = studentParts[0];
                            String name = studentParts[1];
                            String className = studentParts[2];
                            Student student = new Student(studentId, name, className);
                            loadedStudents.add(student);
                        }
                        break;

                    case "score":
                        // 解析成绩：学号,课程编号,成绩
                        String[] scoreParts = line.split(",");
                        if (scoreParts.length == 3) {
                            String studentId = scoreParts[0];
                            String courseId = scoreParts[1];
                            double score = Double.parseDouble(scoreParts[2]);

                            // 找到对应的学生和课程
                            Student student = findStudentById(studentId, loadedStudents);
                            Course course = findCourseById(courseId, loadedCourses);
                            if (student != null && course != null) {
                                try {
                                    Score newScore = new Score(student, course, score);
                                    loadedScores.add(newScore);
                                } catch (InvalidScoreException e) {
                                    System.err.println("加载成绩失败：" + e.getMessage());
                                }
                            }
                        }
                        break;
                }
            }

            // 加载完成，更新系统集合
            this.courseList = loadedCourses;
            this.studentList = loadedStudents;
            this.scoreList = loadedScores;

            System.out.println("历史数据加载成功！");
            System.out.println("统计：学生" + studentList.size() + "人 | 课程" + courseList.size() + "门 | 成绩" + scoreList.size() + "条");

        } catch (IOException e) {
            System.err.println("数据加载失败：" + e.getMessage());
        } catch (NumberFormatException e) {
            System.err.println("数据格式错误（可能手动修改过CSV文件）：" + e.getMessage());
        }
    }

    // ---------------------- 辅助方法1：通过学号查找学生（系统内使用） ----------------------
    private Student findStudentById(String studentId) {
        for (Student student : studentList) {
            if (student.getStudentId().equals(studentId)) {
                return student;
            }
        }
        return null;
    }

    // ---------------------- 辅助方法2：通过课程编号查找课程（系统内使用） ----------------------
    private Course findCourseById(String courseId) {
        for (Course course : courseList) {
            if (course.getCourseId().equals(courseId)) {
                return course;
            }
        }
        return null;
    }

    // ---------------------- 辅助方法3：加载数据时，从指定列表找学生 ----------------------
    private Student findStudentById(String studentId, List<Student> students) {
        for (Student student : students) {
            if (student.getStudentId().equals(studentId)) {
                return student;
            }
        }
        return null;
    }

    // ---------------------- 辅助方法4：加载数据时，从指定列表找课程 ----------------------
    private Course findCourseById(String courseId, List<Course> courses) {
        for (Course course : courses) {
            if (course.getCourseId().equals(courseId)) {
                return course;
            }
        }
        return null;
    }

    // ---------------------- 测试主方法 ----------------------
    public static void main(String[] args) {
        StudentScoreSystem system = new StudentScoreSystem();
        system.loadData();

        // 1. 添加课程
        system.addCourse(new Course("CS101", "Java编程", 4));
        system.addCourse(new Course("CS102", "数据结构", 3));
        system.addCourse(new Course("CS101", "Python编程", 3)); // 重复编号，添加失败

        // 2. 添加学生
        system.addStudent(new Student("2023001", "张三", "计算机2301"));
        system.addStudent(new Student("2023002", "李四", "计算机2301"));

        // 3. 添加成绩（含异常测试：105分）
        system.addScore("2023001", "CS101", 85);  // 正常
        system.addScore("2023001", "CS102", 92);  // 正常
        system.addScore("2023002", "CS101", 78);  // 正常
        system.addScore("2023002", "CS102", 105); // 异常：超过100分

        // 4. 查询成绩
        System.out.println("\n=====课程编号CS101的成绩=====");
        for (Score score : system.queryScoresByCourseId("CS101")) {
            System.out.println(score);
        }

        // 5. 计算GPA
        System.out.println("\n=====GPA结果=====");
        System.out.println("张三的GPA：" + system.calculateGPA("2023001"));
        System.out.println("李四的GPA：" + system.calculateGPA("2023002"));

        // 6. 保存数据
        system.saveData();
    }
}